package cn.gson;

import java.lang.reflect.Type;
import java.sql.*;
import java.util.*;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;

import com.sun.corba.se.spi.orbutil.fsm.Guard.Result;

public class BaseDao {
	private String URL = "jdbc:mysql://localhost:3306/shopping?characterEncoding=UTF-8&amp;useUnicode=true";
	private String user = "root";
	private String pass = "123456";
	private Connection conn = null;
	private PreparedStatement pst = null;
	private ResultSet rs = null;

	/**
	 * 创建连接对象：连接池
	 * 
	 * @throws Exception
	 */
	void createConnetion() throws Exception {
		Context initContext = new InitialContext();
		DataSource ds = (DataSource) initContext.lookup("java:/comp/env/jdbc/ecm");
		conn = ds.getConnection();
	}

	/**
	 * 创建执行对象
	 * 
	 * @param sql
	 * @throws Exception
	 */
	void createStatement(String sql, Object... objects) throws Exception {
		// 调用连接对象
		this.createConnetion();
		try {
			pst = conn.prepareStatement(sql);
			// 判断参数是否为空
			if (objects != null) {
				for (int i = 0; i < objects.length; i++) {
					pst.setObject(i + 1, objects[i]);
				}
			}
		} catch (SQLException e) {
			throw new Exception("服务器创建执行对象失败!");
		}
	}

	/**
	 * 修改数据方法：添、删、改
	 * 
	 * @param sql
	 * @param objects
	 * @return
	 * @throws Exception
	 */
	public int excuteUpdate(String sql, Object... objects) throws Exception {
		int row = 0;
		// 调用创建执行对象
		this.createStatement(sql, objects);
		// 执行修改
		row = pst.executeUpdate();
		// 释放资源
		this.release();
		return row;
	}

	/**
	 * 释放资源
	 * 
	 * @throws Exception
	 */
	void release() throws Exception {
		try {
			if (rs != null) {
				rs.close();
			}
			if (pst != null) {
				pst.close();
			}
			if (conn != null) {
				conn.close();
			}
		} catch (SQLException e) {
			throw new Exception("服务器释放资源失败!");
		}
	}

	/**
	 * 查询方法:返回多个值(多个列)
	 * 
	 * @param sql
	 * @param objects
	 * @return
	 * @throws Exception
	 */
	<T> List<T> excuteQuery(String sql, FillData<T> fillData, Object... objects) throws Exception {
		// 调用创建执行对象的方法
		this.createStatement(sql, objects);
		// 调用获取结果的方法
		List<Map<String, Object>> list = this.fillMap();
		List<T> listAll = new ArrayList<T>();
		for (int i = 0; i < list.size(); i++) {
			// 取某一行
			Map<String, Object> x = list.get(i);
			listAll.add(fillData.fillData(x));
		}
		return listAll;
	}

	/**
	 * 将ResultSet结果集的数据,封装到了List集合
	 * 
	 * @return
	 * @throws Exception
	 */
	List<Map<String, Object>> fillMap() throws Exception {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		try {
			rs = pst.executeQuery();
			// 将结果集的每一条记录,用Map集合保存,再将Map存放到List

			// 获取结果集的列
			ResultSetMetaData cols = rs.getMetaData();
			// 用来存放所有列名
			String[] colNames = new String[cols.getColumnCount()];
			for (int i = 0; i < colNames.length; i++) {
				colNames[i] = cols.getColumnName(i + 1);
			}

			// 根据列名,获取rs中的数据
			while (rs.next()) {
				// map中表示一条记录
				Map<String, Object> map = new HashMap<String, Object>();
				for (String n : colNames) {
					map.put(n, rs.getObject(n));
				}
				// 将map存放到集合
				list.add(map);
			}
			// 释放资源
			this.release();
			return list;
		} catch (SQLException e) {
			e.printStackTrace();
			throw new Exception("服务器结果集填充装失败!");
		}
	}

	/**
	 * 查询单个对象
	 * 
	 * @param sql
	 * @param fillData
	 * @param objects
	 * @return
	 * @throws Exception
	 */
	<T> T excuteQueryOne(String sql, FillData<T> fillData, Object... objects) throws Exception {
		// 调用创建执行对象方法
		this.createStatement(sql, objects);
		// 执行查询，并获取查询结果
		rs = pst.executeQuery();

		// 获取结果集的列数
		ResultSetMetaData cols = rs.getMetaData();
		// 用来存放所有列名
		String[] colNames = new String[cols.getColumnCount()];
		for (int i = 0; i < colNames.length; i++) {
			colNames[i] = cols.getColumnName(i + 1);
		}
		Map<String, Object> map = new HashMap<String, Object>();
		// 将查询结果进行封装
		if (rs.next()) {
			for (String n : colNames) {
				map.put(n, rs.getObject(n));
			}
		}
		// 释放资源
		this.release();
		// 调用fillData中的方法,将map数据转为对应的实体对象
		return fillData.fillData(map);
	}

	/**
	 * 查询单个值
	 * 
	 * @param sql
	 * @param objects
	 * @return
	 * @throws Exception
	 */
	Object excuteQueryObject(String sql, Object... objects) throws Exception {
		// 调用创建执行对象方法
		this.createStatement(sql, objects);
		// 执行查询，并获取查询结果
		rs = pst.executeQuery();
		Object obj = null;
		// 获取结果
		if (rs.next()) {
			obj = rs.getObject(1);
		}
		// 释放资源
		this.release();
		return obj;
	}

}
